package tech.dongling.boot;

import cn.hutool.core.date.StopWatch;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tech.dongling.boot.common.parser.ProtocolServerInitializer;
import tech.dongling.boot.ioc.BeanScanner;
import tech.dongling.boot.ioc.LightIocContainer;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class FrameworkBootstrap {
    private static final Logger logger = LoggerFactory.getLogger(FrameworkBootstrap.class);

    public static void main(String[] args) throws InterruptedException {
        StopWatch watch = new StopWatch();
        watch.start();
        Properties config = loadProperties();

        // 初始化IOC容器
        LightIocContainer ioc = new LightIocContainer();

        // 使用Bean扫描器自动注册Bean
        BeanScanner beanScanner = new BeanScanner(ioc);
        beanScanner.scan("tech.dongling.boot.example");
        watch.stop();
        logger.info("Init bean seccess use times {}ms", watch.getTotalTimeMillis());
        // 从配置中获取端口，默认8080
        int port = Integer.parseInt(config.getProperty("server.port", "8080"));


        // 启动Netty服务器
        NioEventLoopGroup boss = new NioEventLoopGroup(1);
        NioEventLoopGroup worker = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ProtocolServerInitializer(ioc, config));

            ChannelFuture future = bootstrap.bind(port).sync();
            logger.info("Server started on port {}", port);
            future.channel().closeFuture().sync();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }

    /**
     * 从 resources 目录加载 boot.properties 配置文件
     */
    private static Properties loadProperties() {
        Properties properties = new Properties();
        try (InputStream inputStream = FrameworkBootstrap.class.getClassLoader()
                .getResourceAsStream("boot.properties")) {
            if (inputStream != null) {
                properties.load(inputStream);
                logger.info("Successfully loaded boot.properties");
            } else {
                logger.warn("boot.properties not found in resources, using default configuration");
            }
        } catch (IOException e) {
            logger.error("Failed to load boot.properties: {}", e.getMessage());
        }
        return properties;
    }
}